﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Telerik.Web.UI;

namespace KPIS.GERP.GHRMS.APP.App_UI.Controls
{
	public class MyTemplate : System.Web.UI.ITemplate
	{
		System.Web.UI.WebControls.ListItemType templateType;
		private List<string> _columnText; 
		public MyTemplate(System.Web.UI.WebControls.ListItemType type, List<string> columnText)
		{
			templateType = type;
			_columnText = columnText;
		}

		public void InstantiateIn(System.Web.UI.Control container)
		{
			PlaceHolder ph = new PlaceHolder();
			Label item1 = new Label();
			Label item2 = new Label();
			item1.ID = "item1";
			item2.ID = "item2";


			Unit widthPerCell = Unit.Percentage(Convert.ToInt32(100 / (_columnText.Count > 0 ? _columnText.Count : 1)));

			switch (templateType)
			{
				case ListItemType.Header:
					var tableHeader = new Table {Width = Unit.Percentage(100)};
					var trh = new TableRow();
					foreach (string columnText in _columnText)
					{
						trh.Cells.Add(new TableCell
							{
								Text = columnText,
								Width = widthPerCell,
								CssClass = "ComboboxGridHeader"
							});
					}
					tableHeader.Rows.Add(trh);
					container.Controls.Add(tableHeader);
					container.Controls.Add(tableHeader);
					break;
				case ListItemType.Item:
					var tableData = new Table {Width = Unit.Percentage(100)};
					var trc = new TableRow();
					foreach (string columnText in _columnText)
					{
						trc.Cells.Add(new TableCell
							{
								Width = widthPerCell,
								CssClass = "ComboboxGridCell"
							});
					}
					tableData.Rows.Add(trc);
					container.Controls.Add(tableData);
					break;
			} 
		} 
	}

	public partial class ComboBoxGrid : UserControl
	{ 
		private class ConfigurationCbbGrid
		{
			private class TestClass
			{
				List<string> Med1()
				{
					return new List<string> { "XX", "YY" };
				}
				List<string> Med1(string par1)
				{
					return new List<string> { "XX", "YY", "ZZ"};
				}
			}
			public object Data { get; set; }
			public Type MethodClassType { get; set; }
			public string MethodName { get; set; }
			public Type[] MethodParamType { get; set; }
			public object[] MethodParam { get; set; }
			public List<string> ColumnText { get; set; }
			public List<string> ColumnNames { get; set; }
			public string FieldKeyToCompare { get; set; }
			public string FieldText { get; set; }
			public int ItemCount { get; set; }
			public int ItemPerRequest { get; set; }

			public void GetList()
			{
				Data = CallMethod(MethodClassType, MethodName, MethodParamType, MethodParam) ?? new List<object>();

				string typeString = Data.GetType().Name;
				
				if(typeString == "DataTable")
					ItemCount = ((DataTable) Data).Rows.Count;

				if(typeString == "DataSet")
					ItemCount = ((DataSet) Data).Tables[0].Rows.Count;
				 
				if(typeString.StartsWith("IList") || typeString.StartsWith("List"))
					ItemCount = ((IList)Data).Count;

			}

			private object CallMethod(Type type, String mymethod, Type[] paramType = null, object[] param = null)
			{
				try
				{
					if (paramType == null)
						paramType = new Type[0];
					if (param == null)
					{
						param = new object[paramType.Length];
						for (int i = 0; i < param.Length; i++)
						{
							param[i] = null;
						}
					}
					// Get a type from the string 
					//Type type = Type.GetType(myclass);
					// Create an instance of that type
					Object obj = Activator.CreateInstance(type);
					// Retrieve the method you are looking for
					MethodInfo methodInfo = type.GetMethod(mymethod, paramType);
					// Invoke the method on the instance we created above
					return methodInfo.Invoke(obj, param);
				}
				catch (Exception e)
				{
					throw e;
				}
			}
		}

		private ConfigurationCbbGrid configurationCbbGrid = null;
		public void ChangeData(Type methodClassType, string methodName, Type[] methodParamType, object[] methodParam, List<string> columnText, List<string> columnNames, 
			string fieldKeyToCompare, string fieldText, int itemPerRequest, string selectedValue = null)
		{
			configurationCbbGrid = new ConfigurationCbbGrid
				{
					MethodClassType = methodClassType,
					MethodName = methodName,
					MethodParamType = methodParamType,
					MethodParam = methodParam,
					ColumnText = columnText,
					ColumnNames = columnNames,
					FieldKeyToCompare = fieldKeyToCompare,
					FieldText = fieldText,
					ItemPerRequest = itemPerRequest
				};
			cbbg.HeaderTemplate = new MyTemplate(ListItemType.Header, configurationCbbGrid.ColumnText);
			cbbg.ItemTemplate = new MyTemplate(ListItemType.Item, configurationCbbGrid.ColumnText);
			if (!String.IsNullOrEmpty(selectedValue) || !String.IsNullOrEmpty(cbbg.SelectedValue))
			{
				var r = new RadComboBoxItemsRequestedEventArgs {NumberOfItems = 0};
				BindComboBoxWithTableItemRequest(ref r);
				cbbg.LoadingMessage = r.Message;
			}

		}

		protected void Page_Load(object sender, EventArgs e)
		{
			if (!IsPostBack) // Save to session on first time of load
			{
				string summonNewKey = DateTime.Now.ToString("M/d/yyyy h:mm tt");
				Session[summonNewKey] = configurationCbbGrid;
				SessionPersistID.Value = summonNewKey;
			}
			else
			{
				configurationCbbGrid = (ConfigurationCbbGrid)Session[SessionPersistID.Value];
			}
		}

		protected void cbbg_ItemsRequested(object sender, RadComboBoxItemsRequestedEventArgs e)
		{
			BindComboBoxWithTableItemRequest(ref e);
		}

		public void BindComboBoxWithTableItemRequest(ref RadComboBoxItemsRequestedEventArgs e)
		{ 
			try
			{
				configurationCbbGrid.GetList();
				string selectedValue = cbbg.SelectedValue;

				var alreadyInComboBox = new List<string>();
				foreach (RadComboBoxItem item in cbbg.Items)
				{
					alreadyInComboBox.Add(item.Value);
				}

				cbbg.Items.Clear();

				var dataType = configurationCbbGrid.Data.GetType().Name;
				int i = 0, itemOffSet = e.NumberOfItems;
				int endOffset = itemOffSet + configurationCbbGrid.ItemPerRequest;


				if (dataType.StartsWith("List"))
				{
					foreach (object data in (IEnumerable)configurationCbbGrid.Data)
					{
						if (endOffset == i)
						{
							endOffset = Math.Min(endOffset, configurationCbbGrid.ItemCount);
							e.Message = GetStatusMessage(endOffset, configurationCbbGrid.ItemCount);
							return;
						}

						string keyOfEachData = Convert.ToString(data.GetType().GetProperty(configurationCbbGrid.FieldKeyToCompare).GetValue(data, null));
						string textOfEachData = Convert.ToString(data.GetType().GetProperty(configurationCbbGrid.FieldText).GetValue(data, null));

						if (selectedValue == keyOfEachData)
							continue;

						if (i >= itemOffSet && !alreadyInComboBox.Contains(keyOfEachData))
						{

							// Add Default Item
							cbbg.Items.Add(new RadComboBoxItem(textOfEachData, keyOfEachData));

							Table targetTable = null;
							foreach (Control c in cbbg.Items[cbbg.Items.Count - 1].Controls)
							{
								if (c.GetType().Name == "Table")
								{
									targetTable = (Table) c;
									break;
								}

							}

							if (targetTable == null)
							{
								string errorMessage =
									String.Format("Can not find any table in Template of combobox '{0}'.", cbbg.ID);
								throw new Exception(errorMessage);
							}

							int j = 0;
							foreach (string kv in configurationCbbGrid.ColumnNames)
							{
								string fieldTextText = GetValueOfPropertyOfObject(kv, data);
								// Convert.ToString(data.GetType().GetProperty(kv).GetValue(data, null));
								targetTable.Rows[0].Cells[j++].Text = fieldTextText;
							}

							if (keyOfEachData == selectedValue)
							{
								cbbg.Items[i].Selected = true;
							}
						}
						i++;
					}
				}


				if (dataType.Equals("DataTable") || dataType.Equals("DataSet"))
				{
					configurationCbbGrid.Data = dataType.StartsWith("DataSet") ? ((DataSet)configurationCbbGrid.Data).Tables[0] : configurationCbbGrid.Data;

					foreach (DataRow data in ((DataTable)configurationCbbGrid.Data).Rows)
					{
						if (endOffset == i)
						{
							endOffset = Math.Min(endOffset, configurationCbbGrid.ItemCount);
							e.Message = GetStatusMessage(endOffset, configurationCbbGrid.ItemCount);
							return;
						}

						string keyOfEachData = Convert.ToString(data[configurationCbbGrid.FieldKeyToCompare]);
						string textOfEachData = Convert.ToString(data[configurationCbbGrid.FieldText]);

						if (i >= itemOffSet && !alreadyInComboBox.Contains(keyOfEachData))
						{
							// Add Default Item
							cbbg.Items.Add(new RadComboBoxItem(textOfEachData, keyOfEachData));

							Table targetTable = (from Control c in cbbg.Items[cbbg.Items.Count - 1].Controls
							                     where c.GetType().Name == "Table"
							                     select (Table) c).FirstOrDefault();

							if (targetTable == null)
							{
								string errorMessage =
									String.Format("Can not find any table in Template of combobox '{0}'.", cbbg.ID);
								throw new Exception(errorMessage);
							}

							int j = 0;
							foreach (string kv in configurationCbbGrid.ColumnNames)
							{
								targetTable.Rows[0].Cells[j++].Text = String.Format("{0}.[{1}]{2}",
								                                                    (cbbg.Items.Count - 1).ToString(),
								                                                    keyOfEachData,
								                                                    Convert.ToString(data[kv]));
							}

							if (keyOfEachData == selectedValue)
							{
								cbbg.Items[cbbg.Items.Count - 1].Selected = true;
							}
						}
						i++;
					}
				}

			}
			catch (Exception e2)
			{ 
			}
		}

		private string GetValueOfPropertyOfObject(string propertyPath, object data)
		{
			Object o = null;
			foreach (string eachProperyLevel in propertyPath.Split('.'))
			{
				if (o == null)
					o = data.GetType().GetProperty(eachProperyLevel).GetValue(data, null);
				else
					o = o.GetType().GetProperty(eachProperyLevel).GetValue(o, null);
			}

			return Convert.ToString(o);
		}


		private static string GetStatusMessage(int offset, int total)
		{
			if (total <= 0)
				return "ไม่มีข้อมูล";

			return String.Format("รายการที่ <b>1</b>-<b>{0}</b> จากทั้งหมด <b>{1}</b> รายการ", offset, total);
		}

	}
}